package marco.android.CouchControl;

import marco.android.CouchControl.AudioHelper;
import marco.android.CouchControl.R;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;

public class CouchControlActivity extends Activity
{
	private Connection mConnection = null;
	private WakeLock mLock = null;
	private AudioHelper mAudioHelper = null;
	private int mKeyboardType;
	private InputMethodManager mInMgr = null;

	private Event mEvent = new Event();

	public  String sAddress = "00:02:72:A5:CC:06";
	private String mServerAddress = "192.168.1.7";
	//private String mServerIP = "10.0.2.2";
	private int mPort = 35000;
	
	public static final String TAG = "CouchControlActivity";
	
	Connection.IOMode mMode = Connection.IOMode.eNone;
	
	private String mTitle = "";
	private final Handler mHandler = new Handler();
	
	private GLSurface mGLSurface = null;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		// requesting to turn the title OFF
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		// making it full screen
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		
		mKeyboardType = getResources().getConfiguration().keyboard;
		if(mKeyboardType == Configuration.KEYBOARD_NOKEYS)
		{
			mInMgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
		}
		
		Bundle extras = getIntent().getExtras();
		
		if(extras.getBoolean("_doGL") == true)
		{
		   setContentView(R.layout.gl_touch_pad_layout);
		   mGLSurface = (GLSurface)findViewById(R.id.touchPadSurfaceView);
		   mGLSurface.SetEventListener(new EventCallback());
		}
		else
		{
		   setContentView(R.layout.touch_pad);
		   CanvasSurface sv = (CanvasSurface)findViewById(R.id.touchPadSurfaceView);
		   sv.SetEventListener(new EventCallback());
		}
		
		SharedPreferences sp = getSharedPreferences("local", Context.MODE_PRIVATE);
		sAddress = sp.getString("addr", "00:02:72:A5:CC:06");
		
		if(Connection.IOMode.values()[extras.getInt("_mode")] == Connection.IOMode.eWiFi)
		{
		   mConnection = Connection.Instance(this, Connection.IOMode.eWiFi, new ConnectionCallback());
		}
		else if(Connection.IOMode.values()[extras.getInt("_mode")] == Connection.IOMode.eBluetooth)
		{
			mConnection = Connection.Instance(this, Connection.IOMode.eBluetooth, new ConnectionCallback());
		}
		else
		{
			finish();
		}
		
		mServerAddress = extras.getCharSequence("_address").toString();
		if(mConnection != null)
		{
			if(mConnection.GetMode() == Connection.IOMode.eBluetooth)
			{
				sAddress = extras.getString("address");
				mConnection.Initialize(mServerAddress, null);
			}
			else if(mConnection.GetMode() == Connection.IOMode.eWiFi)
			{
				mConnection.Initialize(mServerAddress, mPort);
			}
		}
		
		Button b = (Button) findViewById(R.id.touchPadLeftButton);
		b.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				mAudioHelper.playSound(R.raw.button_click, 1);
				if(mConnection != null)
				{
					mEvent.Source = 'T';
					mEvent.KeyCode = 0x110;
					mEvent.KeyEvent = 1;
					mEvent.Dx = 0;
					mEvent.Dy = 0;
					mConnection.SendEvent(mEvent);
				}	
			}
		});
		
		b = (Button) findViewById(R.id.touchPadRightButton);
		b.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				mAudioHelper.playSound(R.raw.button_click, 1);
				if(mConnection != null)
				{
					mEvent.Source = 'T';
					mEvent.KeyCode = 0x111;
					mEvent.KeyEvent = 1;
					mEvent.Dx = 0;
					mEvent.Dy = 0;
					mConnection.SendEvent(mEvent);
				}	
			}
		});
		
		b = (Button) findViewById(R.id.touchPadMiddleButton);
		b.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				mAudioHelper.playSound(R.raw.button_click, 1);
				if(mConnection != null)
				{
					mEvent.Source = 'T';
					mEvent.KeyCode = 0x112;
					mEvent.KeyEvent = 1;
					mEvent.Dx = 0;
					mEvent.Dy = 0;
					mConnection.SendEvent(mEvent);
				}	
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		MenuInflater mi = getMenuInflater();
		mi.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		// only one item
//		l("onOptionsItemSelected");
//		final int SIZE = mBluetoothAdapter.getBondedDevices().size();
//		final String[] names = new String[SIZE];
//		final String[] addr = new String[SIZE];
//		int i = 0;
//		for(BluetoothDevice d : mBluetoothAdapter.getBondedDevices())
//		{
//			names[i] = d.getName();
//			addr[i] = d.getAddress();
//			i++;
//			if(i >= SIZE)
//				break;
//		}
//		AlertDialog.Builder b = new AlertDialog.Builder(this);
//		b.setTitle("Device");
//		b.setItems(names, new DialogInterface.OnClickListener()
//		{
//			@Override
//			public void onClick(DialogInterface dialog, int which)
//			{
//				sAddress = addr[which];
//				SharedPreferences sp = getSharedPreferences("local", MODE_PRIVATE);
//				sp.edit().putString("addr", sAddress).commit();
//
//				// Restart the BT thread with the new address.
//				restart();
//			}
//		});
//		b.create().show();
		return true;
	}

	@Override
	protected void onPause()
	{
		super.onPause();
		
		if(mGLSurface != null)
		{
			mGLSurface.onPause();
		}
		mAudioHelper.Shutdown();
	}
	
	@Override
	protected void onResume()
	{
		super.onResume();
		
		if(mGLSurface != null)
		{
			mGLSurface.onResume();
		}
		mAudioHelper = AudioHelper.getInstance(this);
		mAudioHelper.addSound(R.raw.button_click, R.raw.button_click);
	}
	
	@Override
	protected void onRestart()
	{
		super.onRestart();
	}
	
	@Override
	protected void onDestroy()
	{
		super.onDestroy();
	}

	@Override
	protected void onStart()
	{
		super.onStart();
		Logs.d(TAG, "onStart");

		// Request a power service lock.
		if(mLock == null)
		{
			PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
			mLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "CouchControl");
		}

		if(mLock.isHeld() != true)
		{
			mLock.acquire();
		}

		if(mConnection != null)
		{
			mConnection.Start();
		}
	}

//	@Override
//	public void onConfigurationChanged(Configuration newConfig)
//	{
//	    super.onConfigurationChanged(newConfig);
//
//	    // Checks the orientation of the screen
//	    if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
//	    {
//	        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
//	    }
//	    else if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
//	    {
//	        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
//	    }
//	    else if(newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO)
//	    {
//	    	Toast.makeText(this, "Keyboard Out", Toast.LENGTH_SHORT).show();
//	    }
//	    else if(newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES)
//	    {
//	    	Toast.makeText(this, "Keyboard Hidden", Toast.LENGTH_SHORT).show();
//	    }
//	}
	
	@Override
	protected void onStop()
	{
		Logs.d(TAG, "onStop");

		if(mConnection != null)
		{
			mConnection.Stop();
		}
		
		// Let go of the power manager lock.
		if(mLock != null && mLock.isHeld())
		{
			mLock.release();
		}
		super.onStop();
	}
	
	private void SendKeyEvent(int keyCode, int keyEvent)
	{
		if(mConnection != null)
		{
			mEvent.Source = 'K';
			mEvent.KeyCode = keyCode;
			mEvent.KeyEvent = keyEvent;
			mEvent.Dx = 0;
			mEvent.Dy = 0;
			mConnection.SendEvent(mEvent);
		}
	}
	
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		if(event.getAction() == KeyEvent.ACTION_DOWN &&
		   event.getRepeatCount() == 0)
		{
			switch(keyCode)
			{
			case(KeyEvent.KEYCODE_BACK):
			case(KeyEvent.KEYCODE_MENU):
				break;
			case(KeyEvent.KEYCODE_SEARCH):
				if(mKeyboardType == Configuration.KEYBOARD_QWERTY)
				{
					// Ignore this key on devices that do not have
					// a hardware/physical keyboard.
				   SendKeyEvent(keyCode, 1 + event.getMetaState());
				   return(true);
				}
				break;
			default:
				SendKeyEvent(keyCode, 1 + event.getMetaState());
				return(true);
			}
		}
		return(super.onKeyDown(keyCode, event));
	}
	
	public boolean onKeyUp(int keyCode, KeyEvent event)
	{
		switch(keyCode)
		{
		case(KeyEvent.KEYCODE_BACK):
		case(KeyEvent.KEYCODE_MENU):
			break;
		case(KeyEvent.KEYCODE_SEARCH):
			if(mKeyboardType == Configuration.KEYBOARD_QWERTY)
			{
				// Ignore this key on devices that do not have
				// a hardware/physical keyboard.
			   SendKeyEvent(keyCode, 0);
			   return(true);
			}
			else if(mInMgr != null)
			{
				mInMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
			}
			break;
		default:
			SendKeyEvent(keyCode, 0);
			return(true);
		}
		return(super.onKeyUp(keyCode, event));
	}
	
	private void UpdateUI()
	{
		setTitle(mTitle);
	}
	
	private final Runnable mUpdateRunnable = new Runnable()
	{
		@Override
		public void run()
		{
			UpdateUI();
		}
	};

	private class ConnectionCallback implements Connection.ConnectionListener
	{
		@Override
		public void StartBluetoothActivityForResult()
		{
			Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableBtIntent, 0);
		}

		@Override
		public void StartWiFiActivityForResult()
		{			
		}

		@Override
		public void UpdateConnectionStatus(String host)
		{
			mTitle = host;
			mHandler.post(mUpdateRunnable);
		}
	};
	
	private class EventCallback implements TouchPadPanel.TouchPadPanelListener
	{
		@Override
		public void onDown(float x, float y)
		{
			
		}
		
		@Override
		public void onMove(float dx, float dy)
		{
			if(mConnection != null)
			{
				mEvent.Source = 'M';
				mEvent.KeyCode = 0;
				mEvent.KeyEvent = 0;
				mEvent.Dx = dx * 2.f;
				mEvent.Dy = dy * 2.f;
				mConnection.SendEvent(mEvent);
			}
		}

		private float mScaleFactor = 1.f;
		@Override
		public void onZoom(float scaleFactor)
		{
			// TODO Auto-generated method stub
			if(mConnection != null)
			{
				mScaleFactor *= scaleFactor;

	    		// Don't let the object get too small or too large.
				mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));
	    		
				mEvent.Source = 'Z';
				mEvent.KeyCode = 0;
				mEvent.KeyEvent = 1;
				mEvent.Dx = mScaleFactor;
				mEvent.Dy = mScaleFactor;
				System.out.println(mScaleFactor);
				mConnection.SendEvent(mEvent);
			}
		}

		@Override
		public void onUp()
		{
			if(mConnection != null)
			{
				mEvent.Source = 'C';
				mEvent.KeyCode = 0;
				mEvent.KeyEvent = 0;
				mEvent.Dx = 0;
				mEvent.Dy = 0;
				mConnection.SendEvent(mEvent);
			}
		}

		@Override
		public void onDoubleTap(float x, float y)
		{
			if(mConnection != null)
			{
				mEvent.Source = 'T';
				mEvent.KeyCode = 0x110;
				mEvent.KeyEvent = 1;
				mEvent.Dx = 0;
				mEvent.Dy = 0;
				mConnection.SendEvent(mEvent);
			}
		}

		@Override
		public void onLongPress(float x, float y)
		{
			if(mConnection != null)
			{
				mEvent.Source = 'L';
				mEvent.KeyCode = 0;
				mEvent.KeyEvent = 1;
				mEvent.Dx = 0;
				mEvent.Dy = 0;
				mConnection.SendEvent(mEvent);
			}
		}

		@Override
		public void onFling(MotionEvent e1, MotionEvent e2, float vX, float vY)
		{
			if(mConnection != null)
			{
				mEvent.Source = 'F';
				mEvent.KeyCode = 0;
				mEvent.KeyEvent = 1;
				mEvent.Dx = 0;
				mEvent.Dy = 0;
				mConnection.SendEvent(mEvent);
			}
		}
	}
}